/**
 * link list implement
 * @author yangjian102621@gmail.com
 */
#include "link.h"

// create a node
static link_list_node_t *create_link_list_node(void *, link_list_node_t *, link_list_node_t *);

/**
 * create a link
 * @return
 */
link_list_t * new_link_list()
{
	link_list_t * link = (link_list_t *) malloc(sizeof(link_list_t));
	link->head = create_link_list_node(NULL, NULL, NULL);
	if (NULL == link->head) {
		free(link);
		return NULL;
	}
	link->tail = create_link_list_node(NULL, link->head, NULL);
	link->head->next = link->tail;
	link->size = 0;
	return link;
}

/**
 * create a link node
 * @param value
 * @param prev
 * @param next
 * @return
 */
static link_list_node_t * create_link_list_node(void * value, link_list_node_t * prev, link_list_node_t * next)
{
	link_list_node_t *node = (link_list_node_t *) malloc(sizeof(link_list_node_t));
	if (NULL == node) {
		perror("malloc error.");
		return NULL;
	}
	node->prev = prev;
	node->next = next;
	node->value = value;
	return node;
}

/**
 * append a node to the tail of link
 * @param link
 * @param value
 */
void link_list_add(link_list_t * link, void * value)
{
	link_list_node_t * node;
	node = create_link_list_node(value, NULL, link->tail);
	link->tail->prev->next = node;
	link->tail->prev = node;
	link->size++;
}

/**
 * destroy the link
 * @param link
 */
void link_list_destroy(link_list_t * link, link_free_callback_fn_t callback_fn)
{
	if (NULL == link) {
		return;
	}
	link_list_node_t * node, *temp;
	node = link->head;
	while (node->next != NULL) {
		temp = node->next;
		if (NULL != callback_fn) {
			callback_fn(node->value);
		}
		free(node);
		node = temp;
	}
	free(link->tail);
	free(link);
}

/**
 * free memory for link node value
 * @param ptr
 */
void free_link_node_value(void * ptr)
{
    free(ptr);
}